#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <modbus.h>
#include "shmem.h"
#include "MQTTClient.h"
#include "cJSON.h"
#define ADDRESS "tcp://mqtt.yyzlab.com.cn:1883"
#define CLIENTIDS "ClientSub"
#define TOPICP "1815652500/APP2AIOTSIM"
#define TOPICP1 "1815652500/AIOTSIM2Device"
#define QOS 1

#define TIMEOUT 10000L

volatile MQTTClient_deliveryToken deliveredtoken;

static struct shm_param para;
static int *total = NULL; // 指向共享内存中数据节点总个数
static struct std_node *node_arr = NULL;

union val_t
{
    int b_val;   // bool类型存储空间
    int i_val;   // 整形值存储空间
    float f_val; // 浮点值存储空间
};

struct std_node
{
    int key;             // 唯一键值
    int type;            // 数据点类型
    int dev_type;        // 数据点属于哪个设备，根据网关支持的设备自行定义
    union val_t old_val; // 变化上报后需要更新旧值
    union val_t new_val; // 从共享内存取出最新数据，放到new_val中
    int ret;             // 默认为-1，采集成功后设置为0，采集失败再置-1
};

void delivered(void *context, MQTTClient_deliveryToken dt)
{
    printf("Message with token value %d delivery confirmed\n", dt);
    deliveredtoken = dt;
}

void connlost(void *context, char *cause)
{
    printf("\nConnection lost\n");
    printf("     cause: %s\n", cause);
}

// 封装发送消息的函数
void publish_message(MQTTClient client, const char *topic, const char *key, const char *value, int id)
{
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;
    int rc;
    char *buffer;

    // 创建JSON对象
    cJSON
        *root = cJSON_CreateObject();
    cJSON_AddItemToObject(root, key, cJSON_CreateString(value));
    cJSON_AddItemToObject(root, "id", cJSON_CreateNumber(id));

    // 转换为字符串并发布
    buffer = cJSON_Print(root);
    pubmsg
        .payload = buffer;
    pubmsg
        .payloadlen = (int)strlen(buffer);
    pubmsg
        .qos = QOS;
    pubmsg
        .retained = 0;

    MQTTClient_publishMessage(client, topic, &pubmsg, &token);
    printf("Publishing: %s\n", buffer);
    rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);

    // 清理资源
    cJSON_Delete(root);
    free(buffer);
}
// 函数2：发送温湿度传感器消息 {"tem": 33, "hum": 11}
void publish_temp_hum_message(MQTTClient client, const char *topic, float temperature, float humidity)
{
    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;
    int rc;
    char *buffer;

    // 创建JSON对象，格式: {"tem": 333, "hum": 11}
    cJSON *root = cJSON_CreateObject();
    cJSON_AddItemToObject(root, "tem", cJSON_CreateNumber(temperature));
    cJSON_AddItemToObject(root, "hum", cJSON_CreateNumber(humidity));

    // 转换为字符串并发布
    buffer = cJSON_Print(root);
    pubmsg.payload = buffer;
    pubmsg.payloadlen = (int)strlen(buffer);
    pubmsg.qos = QOS;
    pubmsg.retained = 0;

    MQTTClient_publishMessage(client, topic, &pubmsg, &token);
    printf("Publishing to %s: %s\n", topic, buffer);
    rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);

    // 清理资源
    cJSON_Delete(root);
    free(buffer);
}

int main(int argc, char *argv[])
{
    // 注意进程双方共享内存的大小一致
    int ret = shm_init(&para, "shm_test", 1024);
    if (ret < 0)
    {
        return -1;
    }

    void *node_p = shm_getaddr(&para);
    if (NULL == node_p)
    {
        printf("共享内存获取地址失败\n");
        return -1;
    }

    total = (int *)node_p;
    *total = 12;
    // printf("%d\n",*total);
    node_arr = (struct std_node *)(node_p + sizeof(int));

    MQTTClient clients;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;

    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    MQTTClient_deliveryToken token;

    int rc;

    MQTTClient_create(&clients, ADDRESS, CLIENTIDS,
                      MQTTCLIENT_PERSISTENCE_NONE, NULL);
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;

    if ((rc = MQTTClient_connect(clients, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
    float tem = 0;
    float hum = 0;
    while (1)
    {
        int i = 0;
        for (i = 0; i < *total; i++)
        {
            //温度传感器
            if (node_arr[i].key == 301)
            {
                tem = node_arr[i].new_val.f_val;
            }
            //湿度传感器
            else if (node_arr[i].key == 302)
            {
                hum = node_arr[i].new_val.f_val;
            }
            //火焰传感器
            else if (node_arr[i].key == 303)
            {
                if (node_arr[i].new_val.b_val == 1)
                {
                    publish_message(clients, TOPICP, "flame", "true", 0);
                }
                else
                {
                    publish_message(clients, TOPICP, "flame", "false", 0);
                }
            }
            //卧室灯
            else if (node_arr[i].key == 304)
            {
                if (node_arr[i].new_val.b_val == 1)
                {
                    publish_message(clients, TOPICP, "lamp", "true", 0);
                }
                else
                {
                    publish_message(clients, TOPICP, "lamp", "false", 0);
                }
            }
            //客厅灯
            else if (node_arr[i].key == 305)
            {
                if (node_arr[i].new_val.b_val == 1)
                {
                    publish_message(clients, TOPICP, "lamp", "true", 1);
                }
                else
                {
                    publish_message(clients, TOPICP, "lamp", "false", 1);
                }
            }
            //空气净化器（风扇）
            else if (node_arr[i].key == 306)
            {
                if (node_arr[i].new_val.b_val == 1)
                {
                    publish_message(clients, TOPICP, "fan", "true", 0);
                }
                else
                {
                    publish_message(clients, TOPICP, "fan", "false", 0);
                }
            }
            //空调开关
            else if (node_arr[i].key == 101)
            {
                if (node_arr[i].new_val.b_val == 1)
                {
                    publish_message(clients, TOPICP, "air", "true", 0);
                }
                else
                {
                    publish_message(clients, TOPICP, "air", "false", 0);
                }
            }
            //加湿器
            else if (node_arr[i].key == 103)
            {
                if (node_arr[i].new_val.b_val == 1)
                {
                    publish_message(clients, TOPICP, "humdifier", "true", 0);
                }
                else
                {
                    publish_message(clients, TOPICP, "humdifier", "false", 0);
                }
            }
            //窗帘
            else if (node_arr[i].key == 104)
            {
                if (node_arr[i].new_val.b_val == 1)
                {
                    publish_message(clients, TOPICP, "sunshade", "forward", 0);
                }
                else
                {
                    publish_message(clients, TOPICP, "sunshade", "stop", 0);
                }
            }
            //扫地机器人
            else if (node_arr[i].key == 105)
            {
                if (node_arr[i].new_val.b_val == 1)
                {
                    publish_message(clients, TOPICP, "robot", "true", 0);
                }
                else
                {
                    publish_message(clients, TOPICP, "robot", "false", 0);
                }
            }
            //洗衣机
            else if (node_arr[i].key == 106)
            {
                if (node_arr[i].new_val.b_val == 1)
                {
                    publish_message(clients, TOPICP, "washer", "true", 0);
                }
                else
                {
                    publish_message(clients, TOPICP, "washer", "false", 0);
                }
            }
        }
        publish_temp_hum_message(clients, TOPICP1, tem, hum);
        sleep(1);
    }
    MQTTClient_disconnect(clients, 10000);
    MQTTClient_destroy(&clients);
    return rc;
}
